package src;

import java.util.Calendar;

public class Moteur {
	private Calendar temps;
	private ListeOrdres ListeAchats = new ListeOrdres();
	private ListeOrdres ListeVentes = new ListeOrdres();
	private double taux;
	
	public Moteur(int annee,int mois,int jours, int heures, int minutes){
		setTemps(annee,mois,jours,heures,minutes);
	}
	public Calendar getTemps() {
		return temps;
	}
	public Calendar creerTemps(int annee,int mois,int jours, int heures, int minutes) {
		Calendar C = Calendar.getInstance();
		C.clear();
		C.set(annee,mois,jours,heures,minutes);
		return C;
	}
	
	public void setTemps(int annee,int mois,int jours, int heures, int minutes) {
		temps = creerTemps(annee,mois,jours,heures,minutes);
	}
	

	public void actualise(int annee,int mois,int jours, int heures, int minutes){
		/*
		 * Met à jour le temps, et exécute les ordres qui peuvent l'être à ce moment, 
		 * en actualisant le taux de l'action.
		 */
		this.setTemps(annee,mois,jours,heures,minutes);
		
		ListeOrdres AchatsActuels = ListeAchats.recupOrdres(temps,true);
		ListeOrdres VentesActuelles = ListeVentes.recupOrdres(temps,true);
		ListeOrdres VentesExecutees = new ListeOrdres();
		ListeOrdres AchatsExecutes = new ListeOrdres();
		
		
		// On a déterminé quels ordres étaient dans la bonne marge de temps, reste à les ranger dans l'ordre qui convient.
		// On utilise un trifusion.
		AchatsActuels.trifusion(true); //tri décroissant
		VentesActuelles.trifusion(false); //tri croissant
		
		if(!AchatsActuels.isEmpty() && !VentesActuelles.isEmpty())
		{
			int k = 0;
			int l = 0;
			while(k<AchatsActuels.size() && l<VentesActuelles.size() && AchatsActuels.get(k).getPrix() > VentesActuelles.get(l).getPrix())
			{
				Ordre Achat = AchatsActuels.get(k);
				Ordre Vente = VentesActuelles.get(l);
			
				if (Achat.getQuantite() < Vente.getQuantite()){
					AchatsExecutes.add(Achat); // L'ordre d'achat est entièrement exécuté.
					Ordre VentePartielle = Vente.clone();
					VentePartielle.setQuantite(Achat.getQuantite());
					VentesExecutees.add(VentePartielle); //On exécute ainsi la portion vendue.
					VentesActuelles.get(l).setQuantite(Vente.getQuantite() - Achat.getQuantite());
					AchatsActuels.DelOrdre(Achat);
					k++;
				} else if(Achat.getQuantite() == Vente.getQuantite()){
					VentesExecutees.add(Vente);
					AchatsExecutes.add(Achat);
					AchatsActuels.DelOrdre(Achat);
					VentesActuelles.DelOrdre(Vente);
					k++;
					l++;
				} else {
					VentesExecutees.add(Vente);
					Ordre AchatPartiel = Achat.clone();
					AchatPartiel.setQuantite(Vente.getQuantite());
					AchatsExecutes.add(AchatPartiel);
					AchatsActuels.get(k).setQuantite(Achat.getQuantite() - Vente.getQuantite());
					VentesActuelles.DelOrdre(Vente);
					l++;
				}
			}
			
			
			// Il reste à fixer le taux pour savoir à quel prix sont exécutés les ordres.
			// Le taux sera la moyenne des deux derniers ordres exécutés,
			// sauf si aucun ordre n'est executé.
			
			if(!AchatsExecutes.isEmpty()) 	//Les deux tableaux ont la même taille car on a éventuellement divisé les ordres.
			{
				this.setTaux((AchatsExecutes.get(0).getPrix() + VentesExecutees.get(0).getPrix())/2);
				// Pour une raison étrange, le dernier élément inséré semble être le premier.
				for(int m=0;m<AchatsExecutes.size();m++)
				{
					AchatsExecutes.get(m).setPrix(this.getTaux());
					VentesExecutees.get(m).setPrix(this.getTaux());
					AchatsExecutes.get(m).execution();
					VentesExecutees.get(m).execution();
					// Inutile de supprimer les ordres, ils seront recouverts par les ordres actuels, 
					// ou n'existent pas dans les listes d'ordres (ordres partiels).
				}
			}
			
			// Ce qui n'a pas été résolu est mis à jour dans la liste.
			ListeAchats = ListeAchats.majOrdres(AchatsActuels,temps);
			ListeVentes = ListeVentes.majOrdres(VentesActuelles,temps);
		}
	}

	public Calendar DecalageTemps(int heures, int minutes)
	{
		Calendar C = Calendar.getInstance();
		C.set(temps.YEAR, temps.MONTH, temps.DAY_OF_MONTH, temps.HOUR + heures, temps.MINUTE + minutes);
		return C;
	}
	
	public void CreerOrdre(Joueur J, String type, double prix,int quantite, Calendar temps){
		Ordre O = new Ordre(J,type, prix,quantite,temps);
		J.addOrdre(O);
		if(type=="ACHAT"){
			ListeAchats.add(O);
		} else if(type=="VENTE") {
			ListeVentes.add(O);
		}
	}
	
	public ListeOrdres getListeAchats() {
		return ListeAchats;
	}
	public void setListeAchats(ListeOrdres listeAchats) {
		ListeAchats = listeAchats;
	}
	public ListeOrdres getListeVentes() {
		return ListeVentes;
	}
	public void setListeVentes(ListeOrdres listeVentes) {
		ListeVentes = listeVentes;
	}
	public double getTaux() {
		return taux;
	}
	public void setTaux(double taux) {
		this.taux = taux;
	}
	
}
